<?php


namespace app\open\service;


use app\admin\model\User;
use app\common\library\Sms as Smslib;
use app\common\model\Business;
use app\admin\model\Play;
use app\common\model\Order;
use app\common\model\OrderCancel;
use app\common\model\OrderProof;
use app\common\model\OrderLog;
use think\Config;
use think\Db;
use think\Exception;
use app\open\service\PlayService;

class OrderService extends BaseService
{

    public function createOrder($mobile, $play, $play_order_no, $channel)
    {
        Db::startTrans();
        try {
            $orderData = [
                'play_order_no' => $play_order_no,
                'shop_no' => $play['shop_no'],
                'play_no' => $play['play_no'],
                'shop_name' => $play['shop_name'],
                'platform_no' => $play['shop_type'],
                'rebate_amt' => $play['shop_settlement'], // 商户要支付的返点金额
                'service_charge_amt' => $play['service_amt'], // 平台手续费金额
                'actual_rebate_amt' => $play['back_money'], // 实际用户得到的返点金额
                'user_pay' => $play['user_pay'], // 满多少
                'place_time' => time(),
                'expire_time' => time() + intval(config('sn_expire')),  // 上传单号的过期时间
                'is_yunzhan' => $channel['id'],
                'proposal' => $mobile,
                'create_by' => 'api',
                'wm_order_sn' => '',
                'service_admin_id' => $play['service_admin_id'],
                'service_admin_by' => $play['service_admin_by'],
            ];
            $order = (new \app\common\model\Order());
            $order->data($orderData)->allowField(true)->save();
            $order['proof'] = [];
            $play = (new \app\admin\model\Play())->lock(true)->where('id', $play['id'])->find();
            //减少剩余名额
            $play->stock = $play->stock - 1;
            $play->chbcconsume = $play->chbcconsume - 1;
            $Redis = new \think\cache\driver\Redis();
            if ($Redis->has('bdbplay'.$play['id'])) {
                $Redis->dec('bdbplay'.$play['id']);
            }
            $play->save();
            // orderlog
            OrderLog::create([
                'play_order_id' => $order['id'],
                'play_order_no' => $play_order_no,
                'is_front' => 3,
                'info' => '报名',
                'create_by' => 'api',
                'create_by_id' => $channel['id'],
            ]);
            Db::commit();
            return $order;
        } catch (Exception $exception) {
            Db::rollback();
            \think\Log::write('活动报名exception=>'.$exception->getMessage());
            return false;
        }
    }

    public function getOrderDetail($orderNo, $where = [])
    {
        $orderObj = new Order();
        $playObj = new Play();
        $where['play_order_no'] = $orderNo;
        $db2 = Db::connect(config('database.db2'));
        $order = $db2->name('play_order')
            ->where($where)
            ->find();
        $data = [];
        if ($order) {
            $play = $db2->name('play')->alias('p')->join('chbc_shop s','s.shop_no=p.shop_no')->field("p.*,s.id as shop_id,s.phone,s.lat,s.lng,s.address,s.logo_pic,sp.qrcode_pic,sp.platform_no,sp.is_xls,sp.elm_appenter,sp.sku as skuList,s.dpzxelm,s.is_sjzp,s.province,s.city,s.area,s.has_qrcode,s.shop_name as sshop_name")->join('chbc_shop_platform sp','sp.shop_no=s.shop_no')->where('p.play_no', $order['play_no'])
            ->find();
            $data['orderNo'] = $orderNo;
            $data['takeoutOrderNo'] = $order['wm_order_sn'];
            $data['orderStatus'] = $order['order_status'];
            if ($order['order_status']==-2) {
                $data['orderStatus'] = $order['order_status'] = -1;
            } elseif ($order['order_status']==1 && !$order['wm_order_sn']) {
                $data['orderStatus'] = $order['order_status'] = 0;
            } elseif ($order['order_status']==-9) {
                $data['orderStatus'] = $order['order_status'] = 3;
            }
            $data['isSettled'] = $order['is_pay'];
            $data['mealPrice'] = floatval($play['user_pay']);
            // $data['cashBackAmount'] = floatval($play['back_money']);
            $data['settlementAmount'] = round($play['shop_settlement']-$play['service_amt'],2);
            $data['expireTime'] = date('Y-m-d H:i:s',$order['expire_time']);
            $data['appletJumpInfo'] = PlayService::getAppletJumpInfo($play);
            $data['reason'] = '';
            if ($order['order_status']==-3) {
                $aftersale = $db2->name('play_order_aftersale')->where(['play_order_no'=>$orderNo,'type'=>'驳回订单'])->find();
                if ($aftersale) {
                    $content = json_decode($aftersale['content'],1);
                    $data['reason'] = $content['remark'];
                }
            }
            $data['preCompletionDeductionAmount'] = 0;
            if ($order['order_status']==3 || $order['order_status']<-6) {
                $aftersale = $db2->name('play_order_aftersale')->where(['play_order_no'=>$orderNo,'type'=>'完成前扣款'])->find();
                if ($aftersale) {
                    $content = json_decode($aftersale['content'],1);
                    $data['reason'] = $content['remark'];
                    $data['preCompletionDeductionAmount'] = $content['amount'];
                }
            }
            $data['postCompletionDeductionAmount'] = round($data['settlementAmount']-$order['actual_rebate_amt'],2);
            // $data['cancelStatus'] = $order['cancel_reason'];
            if ($order['cancel_reason']==4 && $order['order_status']==-1) {
                $aftersale = $db2->name('play_order_aftersale')->where(['play_order_no'=>$orderNo,'type'=>'审核取消订单'])->find();
                if ($aftersale) {
                    $content = json_decode($aftersale['content'],1);
                    $data['reason'] = $content['remark'];
                }
            }
            $data['praiseType'] = $play['scheme_no']-1;
            $data['praiseName'] = $playObj->getSchemeNoTextAttr('',$play);
            $data['needAfterSaleImg'] = '';
            $data['needVideo'] = '';
            $data['postCompletionDeductionList'] = [];
            if ($order['order_status']<-6) {
                $aftersales = $db2->name('play_order_aftersale')->where(['play_order_no'=>$orderNo,'type'=>'客服审核拟取消或扣吃豆通过'])->select();
                foreach ($aftersales as $key => $value) {
                    $content = json_decode($value['content'],1);
                    $postCompletionDeductionList = [];
                    $postCompletionDeductionList['deductionId'] = $value['id'];
                    $postCompletionDeductionList['orderNo'] = $orderNo;
                    $postCompletionDeductionList['deductionMoney'] = round($data['settlementAmount']-$order['actual_rebate_amt']-$order['service_charge_amt'],2);
                    $postCompletionDeductionList['deductionReason'] = $content['yh']['remark'];
                    $postCompletionDeductionList['realDeductionMoney'] = $content['yh']['amount'];
                    $postCompletionDeductionList['createTime'] = $value['create_dt'];
                    $data['postCompletionDeductionList'][] = $postCompletionDeductionList;
                }
            }
            $proof = $db2->name('play_order_proof')->where('play_order_no',$order['play_order_no'])->order('id desc')->field('wm_order_sn,one_image,two_image,three_image,platform_no,supplement,machine_audit_state,actual_pay,machine_audit_desc')->find();
            if ($proof) {
            }
        }
        if ($data) return $data;
        return null;
    }

    public function proof($order, $proof, $data = [], $user_id, $nickname, $is_dissatisfied)
    {
        Db::startTrans();
        try {
            $info = '提交凭据';
            $proof->isUpdate(true)->save($data);
            $order->order_status = 2;
            // 如果是不满意提交
            if ($is_dissatisfied) {
                $order->order_status = -5;
                $info = '不满意提交';
            }
            $order->save();

            // orderlog
            OrderLog::create([
                'play_order_id' => $order['id'],
                'play_order_no' => $order['play_order_no'],
                'create_by' => $nickname,
                'create_by_id' => $user_id,
                'is_front' => 1,
                'info' => $info,
            ]);
            Db::commit();
            return ['code' => 200, 'msg' => '成功'];
        } catch (Exception $exception) {
            Db::rollback();
            return ['code' => 400, 'msg' => $exception->getMessage()];
            \think\Log::write('提交活动凭据exception=>'.$exception->getMessage());
        }
    }

    /**
     * @param $order
     * @param int $cancelType '1': '用户取消', '2': '超时取消', '3': '商家取消', '4': '管理员取消'
     * @param array $extend
     * @return bool
     */
    public function cancel($order, $cancelType = 1)
    {
        Db::startTrans();
        try {
            $orderCancelObj = new OrderCancel();
            $order->order_status = -1;
            $order->cancel_reason = 1;
            $order->update_by = 'api';
            $order->save();
            $play_order_no = $order['play_order_no'];
            //库存回归
            $play = (new Play())->lock(true)->where(['play_no' => $order->play_no])->find();
            $play->stock = $play->stock + 1;
            $play->chbcconsume = $play->chbcconsume + 1;
            $play->isUpdate(true)->save();
            $Redis = new \think\cache\driver\Redis();
            if ($Redis->has('bdbplay'.$play['id'])) {
                $Redis->inc('bdbplay'.$play['id']);
            }
            // 改变活动状态
            // $complete_order = Db::name('play_order')->where(['play_no'=>$order['play_no'],'order_status'=>['in',[3,6,-9]]])->count();
            // if (($complete_order==$play['chbcquota'] && $play['play_status']==2) || ($play['play_status']==4 && $complete_order==$play['chbcquota']-$play['chbcconsume'] && $play['chbcquota']-$play['chbcconsume']>0)) {
            //     $play->play_status = 3;
            //     $play->acture_total_money = (float)Db::name('play_order')->where(['play_no'=>$order['play_no'],'order_status'=>['in',[3,6,-9]]])->value('sum(actual_rebate_amt+service_charge_amt)');
            //     $play->save();
            // }

            // orderlog
            OrderLog::create([
                'play_order_id' => $order['id'],
                'play_order_no' => $play_order_no,
                'create_by' => 'api',
                'create_by_id' => $order['is_yunzhan'],
                'is_front' => 3,
                'info' => '取消订单',
            ]);
            Db::commit();
            return true;
        } catch (Exception $e) {
            Db::rollback();
            \think\Log::write('取消活动exception=>'.$e->getMessage());
            return false;
        }
    }


    public static function ip2address($ip,$type=1)
    {
        if ($type==1) {
            $dbFile = ROOT_PATH.'ip2region.xdb';
            $XdbSearcher = new \services\XdbSearcher($dbFile);
            $searcher = $XdbSearcher->newWithFileOnly($dbFile);
            $region = $searcher->search($ip);
            if ($region) {
                return explode('|', $region);
            }
        } else {
            $config = get_addon_config('address');
            $maptype = $config['maptype'];
            if (!isset($config[$maptype . 'key']) || !$config[$maptype . 'key']) {
                return false;
            }
            $res = file_get_contents("https://apis.map.qq.com/ws/location/v1/ip?ip=".$ip."&output=json&key=".$config[$maptype . 'key']);
            $decode = json_decode($res,1);
            if (isset($decode['status']) && $decode['status']==0) {
                return $res;
            }
        }
        return false;
    }



    public static function point2address($lat,$lng)
    {
        $config = get_addon_config('address');
        $maptype = $config['maptype'];
        if (!isset($config[$maptype . 'key']) || !$config[$maptype . 'key']) {
            return false;
        }
        $res = file_get_contents("https://apis.map.qq.com/ws/geocoder/v1/?location=".$lat.",".$lng."&output=json&key=".$config[$maptype . 'key']);
        $decode = json_decode($res,1);
        if (isset($decode['status']) && $decode['status']==0) {
            return $res;
        }
        return false;
    }


    public function proofImg($shop_name,$wm_order_sn,$order_time,$actual_pay,$shop_type)
    {
        $order_time = substr($order_time,0,19);
        $mb_strlen = mb_strlen($shop_name);
        if (!$actual_pay) $actual_pay = '--';
        if ($mb_strlen>25) {
            // 如果字母大于10个，截取数量相应加长
            $matches = [];
            preg_match_all('/[a-zA-Z]/', $shop_name, $matches);
            $letterCount = count($matches[0]);
            if ($letterCount>10) {
                $shop_name = mb_substr($shop_name,0,$letterCount+15).'...';
            } else {
                $shop_name = mb_substr($shop_name,0,25).'...';
            }
            $x = 75;
        } else {
            $x = (25-$mb_strlen)*10+65+10;
        }
        $arr = [
            [$shop_name,$x,446],
            [$wm_order_sn,205,477],
            [$order_time,223,508],
            [$actual_pay,304,539],
        ];
        $resimg = $this->buildImg($arr,$shop_type);
        if ($resimg) {
            return $resimg;
        }
        return '';
    }


    /**
     * 订单扣款通知进入redis和数据库记录
     * @param  [type] $deductionId     [扣款标识]
     * @param  [type] $orderNo         [平台订单号]
     * @param  [type] $deductionMoney  [扣款金额]
     * @param  [type] $deductionReason [扣款原因]
     * @param  [type] $createTime      [发生时间]
     * @return [type]                  [description]
     */
    public function deduction($deductionId,$orderNo,$deductionMoney,$deductionReason,$channelid,$orderStatus)
    {
        $channel = Db::name('channel')->where('id',$channelid)->find();
        if (!$channel) {
            return false;
        }
        $clientId = $channel['clientId'];
        $clientSecret = $channel['clientSecret'];
        $deductUrl = $channel['deductUrl'];
        $data = [];
        $data['deductionId'] = $deductionId;
        $data['orderNo'] = $orderNo;
        $data['deductionMoney'] = $deductionMoney;
        $data['deductionReason'] = $deductionReason;
        $data['orderStatus'] = $orderStatus;
        $data['createTime'] = date('Y-m-d H:i:s');
        $data['clientId'] = $clientId;
        $Redis = new \think\cache\driver\Redis();
        $time = time();
        $zsetkey = 'qddeduction';
        // 如果有预处理数据就使用预处理数据
        $value = json_encode($data,JSON_UNESCAPED_UNICODE);
        $Redis->zAdd($zsetkey,$time,$value);
        Db::name('channel_notify')->insert([
            'orderNo' => $orderNo,
            'content' => $value,
            'type' => 2,
            'order_status' => $orderStatus,
        ]);
        return true;
    }


    /**
     * 订单状态变更通知进入redis和数据库记录
     * @param  [type] $takeoutOrderNo     [外卖订单号]
     * @param  [type] $orderNo         [平台订单号]
     * @param  [type] $orderStatus  [订单状态]
     * @param  [type] $debitAmount [扣款金额]
     * @param  [type] $settlementAmount      [结算金额]
     * @param  [type] $updateTime      [更新时间]
     * @return [type]                  [description]
     */
    public function statusChange($takeoutOrderNo,$orderNo,$orderStatus,$debitAmount,$settlementAmount,$channelid)
    {
        $channel = Db::name('channel')->where('id',$channelid)->find();
        if (!$channel) {
            return false;
        }
        $clientId = $channel['clientId'];
        $clientSecret = $channel['clientSecret'];
        $notifyUrl = $channel['notifyUrl'];
        $data = [];
        $data['takeoutOrderNo'] = $takeoutOrderNo;
        $data['orderNo'] = $orderNo;
        $data['orderStatus'] = $orderStatus;
        // $data['debitAmount'] = $debitAmount;
        // $data['settlementAmount'] = $settlementAmount;
        $data['updateTime'] = date('Y-m-d H:i:s');
        $data['clientId'] = $clientId;
        $Redis = new \think\cache\driver\Redis();
        $time = time();
        $zsetkey = 'qdnotify';
        // 初始化zset数据和过期时间
        // $Redis->zAdd($zsetkey,100000,'{"distance":100000}');
        // 如果有预处理数据就使用预处理数据
        $value = json_encode($data);
        $Redis->zAdd($zsetkey,$time,$value);
        Db::name('channel_notify')->insert([
            'orderNo' => $orderNo,
            'content' => $value,
            'order_status' => $orderStatus,
        ]);
        return true;
    }

    // 签名
    protected function sign($param,$clientSecret)
    {
        ksort($param);
        $md5str = '';
        foreach ($param as $key => $value) {
            if(!is_array($value) && "@" != substr($value, 0, 1))
            {
                $md5str .= $key.$value;
            }
        }
        // $sign = hash_hmac('md5', $md5str, self::clientSecret);
        $sign = strtoupper(md5($clientSecret.$md5str.$clientSecret));
        return $sign;
    }
}